<template>
  <el-card style="max-width: 100%">
    <template #header>
      <div class="card-header">
        <span>无风偏情况下射击参数计算</span>
      </div>
    </template>
    <el-table :data="vectorListTableData" style="width: 100%">
      <el-table-column label="向量名称" width="180">
        <template #default="scope">
          <div style="display: flex; align-items: center">
            <el-input
              type="textarea"
              :autosize="{ minRows: 1, maxRows: 2 }"
              v-model="scope.row.name"
              placeholder="请输入向量名"
            />
          </div>
        </template>
      </el-table-column>
      <el-table-column label="距离" width="100">
        <template #default="scope">
          <el-input v-model="scope.row.distance" placeholder="请输入距离" />
        </template>
      </el-table-column>
      <el-table-column label="方位角" width="100">
        <template #default="scope">
          <el-input v-model="scope.row.angle" placeholder="请输入方向角" />
        </template>
      </el-table-column>
      <el-table-column label="操作" width="230">
        <template #default="scope">
          <el-button size="small" @click="handleAdd(scope.$index, scope.row)" type="primary">
            增加
          </el-button>
          <el-button
            size="small"
            @click="handleInvertVecotr(scope.$index, scope.row)"
            type="primary"
          >
            翻转180度
          </el-button>
          <el-button
            v-if="scope.$index != 0"
            size="small"
            type="danger"
            @click="handleDelete(scope.$index, scope.row)"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="fromular">计算公式：向量1 + 向量2 + ..... = 火炮射击向量</div>
    <template #footer>
      <el-row :gutter="5">
        <el-col :span="8" class="childMiddle">
          <el-tag type="warning">计算结果</el-tag>
          <span>火炮射击向量（不考虑风偏）：</span>
        </el-col>
        <el-col :span="8" class="childMiddle">
          <span>距离：</span>
          <el-tag type="primary">{{ shotVector.distance.toFixed(1) }}</el-tag>
        </el-col>
        <el-col :span="8" class="childMiddle">
          <span>方位角：</span>
          <el-tag type="primary">{{ shotVector.angle.toFixed(1) }}</el-tag>
        </el-col>
      </el-row>
    </template>
  </el-card>
  <div class="divider"></div>

  <el-card style="max-width: 100%">
    <template #header>
      <div class="card-header">
        <span>风偏测量工具</span>
      </div>
    </template>
    <el-button
      type="primary"
      @click="windVectorMeasurementDataGetNoWindEffectShotVector"
      size="large"
    >
      填入不考虑风偏的射击向量：
      <br />
      {{ '距离' + shotVector.distance.toFixed(1) + ' 方位角' + shotVector.angle.toFixed(1) }}
    </el-button>
    <el-table :data="windVectorMeasurementData" style="width: 100%">
      <el-table-column label="向量名称" width="140">
        <template #default="scope">
          <div style="display: flex; align-items: center">
            <span>{{ scope.row.name }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="距离" width="220">
        <template #default="scope">
          <el-button-group>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('sub', 5, scope.$index, 'distance')"
              >-5
            </el-button>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('sub', 1, scope.$index, 'distance')"
              >-1
            </el-button>
          </el-button-group>
          <el-input v-model="scope.row.distance" placeholder="请输入距离" style="width: 60px" />
          <el-button-group>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('add', 1, scope.$index, 'distance')"
              >+1
            </el-button>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('add', 5, scope.$index, 'distance')"
              >+5
            </el-button>
          </el-button-group>
        </template>
      </el-table-column>
      <el-table-column label="方位角" width="220">
        <template #default="scope">
          <el-button-group>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('sub', 5, scope.$index, 'angle')"
              >-5
            </el-button>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('sub', 1, scope.$index, 'angle')"
              >-1
            </el-button>
          </el-button-group>
          <el-input v-model="scope.row.angle" placeholder="请输入方向角" style="width: 60px" />
          <el-button-group>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('add', 1, scope.$index, 'angle')"
              >+1
            </el-button>
            <el-button
              type="success"
              circle
              @click="handleChangeNumClick('add', 5, scope.$index, 'angle')"
              >+5
            </el-button>
          </el-button-group>
        </template>
      </el-table-column>
    </el-table>
    <div class="fromular">计算公式：-(风偏矫正后射击向量 - 不考虑风偏的射击向量) = 风偏向量</div>
    <template #footer>
      <el-row :gutter="5">
        <el-col :span="8" class="childMiddle">
          <el-tag type="warning">计算结果</el-tag>
          <span>风偏向量：</span>
        </el-col>
        <el-col :span="8" class="childMiddle">
          <span>距离：</span>
          <el-tag type="primary">{{ windVector.distance.toFixed(1) }}</el-tag>
        </el-col>
        <el-col :span="8" class="childMiddle">
          <span>方位角：</span>
          <el-tag type="primary">{{ windVector.angle.toFixed(1) }}</el-tag>
        </el-col>
      </el-row>
    </template>
  </el-card>
  <div class="divider"></div>

  <el-card style="max-width: 100%">
    <template #header>
      <div class="card-header">
        <span>风偏修正工具</span>
      </div>
    </template>
    <el-button type="primary" @click="windCorrectorDataGetNoWindEffectShotVector" size="large">
      填入不考虑风偏的射击向量：
      <br />
      {{ '距离' + shotVector.distance.toFixed(1) + ' 方位角' + shotVector.angle.toFixed(1) }}
    </el-button>
    <el-button type="primary" @click="windCorrectorDataGetWindVector" size="large">
      填入风偏向量：
      <br />
      {{ '距离' + windVector.distance.toFixed(1) + ' 方位角' + windVector.angle.toFixed(1) }}
    </el-button>
    <el-table :data="windCorrectorData" style="width: 100%">
      <el-table-column label="向量名称" width="140">
        <template #default="scope">
          <div style="display: flex; align-items: center">
            <span>{{ scope.row.name }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="距离" width="140">
        <template #default="scope">
          <el-input v-model="scope.row.distance" placeholder="请输入距离" style="width: 80px" />
        </template>
      </el-table-column>
      <el-table-column label="方位角" width="140">
        <template #default="scope">
          <el-input v-model="scope.row.angle" placeholder="请输入方向角" style="width: 80px" />
        </template>
      </el-table-column>
    </el-table>
    <div class="fromular">计算公式：不考虑风偏的射击向量 - 风偏向量 = 风偏矫正后射击向量</div>
    <template #footer>
      <el-row :gutter="5">
        <el-col :span="8" class="childMiddle">
          <el-tag type="warning">计算结果</el-tag>
          <span>风偏矫正后射击向量：</span>
        </el-col>
        <el-col :span="8" class="childMiddle">
          <span>距离：</span>
          <el-tag type="primary">{{ correctedShotVector.distance.toFixed(1) }}</el-tag>
        </el-col>
        <el-col :span="8" class="childMiddle">
          <span>方位角：</span>
          <el-tag type="primary">{{ correctedShotVector.angle.toFixed(1) }}</el-tag>
        </el-col>
      </el-row>
    </template>
  </el-card>
</template>

<script lang="ts" setup>
import { ElTableColumn, ElButton, ElTable, ElInput } from 'element-plus'
import { ref, watch } from 'vue'
import type { Ref } from 'vue'

interface PolarVector {
  name: string
  angle: number
  distance: number
}
interface CartesianVector {
  name: string
  x: number
  y: number
}

// ==================无风偏射击向量计算===========================
// #region
const handleAdd = (index: number, row: PolarVector) => {
  console.log(row)
  vectorListTableData.value.splice(index + 1, 0, { name: '新向量', angle: 0, distance: 0 })
}
const handleDelete = (index: number, row: PolarVector) => {
  console.log(row)
  vectorListTableData.value.splice(index, 1)
}

/**
 * 向量取反按钮回调
 * @param index
 * @param row
 */
const handleInvertVecotr = (index: number, row: PolarVector) => {
  console.log(row)
  vectorListTableData.value.splice(index, 1, invertVector(row))
}
// 向量数组（表格数据源）
const vectorListTableData: Ref<PolarVector[]> = ref([
  {
    name: '火炮到观察手',
    angle: 0,
    distance: 0,
  },
  {
    name: '观察手到目标',
    angle: 0,
    distance: 0,
  },
])
// 不考虑风偏的射击向量（由表格数据源计算得到）
const shotVector: Ref<PolarVector> = ref({
  name: 'shotVector',
  angle: 0,
  distance: 0,
})

/**
 * 射击向量计算按钮回调函数
 */
const handleCalculate = () => {
  const result = vectorAddition(vectorListTableData.value)
  shotVector.value = result
  console.log(result)
}
/**
 * 处理向量加法
 */
const vectorAddition = (vectorList: PolarVector[]): PolarVector => {
  // 转换为直角坐标形式再进行相加
  let theSumOfX: number = 0
  let theSumOfY: number = 0
  for (let i = 0; i < vectorList.length; i++) {
    theSumOfX += vectorList[i].distance * Math.cos((vectorList[i].angle * Math.PI) / 180)
    theSumOfY += vectorList[i].distance * Math.sin((vectorList[i].angle * Math.PI) / 180)
  }
  // 转换为极坐标形式返回
  return cartesianToPolar({ name: 'shotVector', x: theSumOfX, y: theSumOfY })
}
// 侦听变化，自动计算射击向量
watch(vectorListTableData, handleCalculate, { deep: true })
// #endregion
// ==================风偏测量工具===========================
// #region
// 风偏测量表格数据源
const windVectorMeasurementData: Ref<PolarVector[]> = ref([
  {
    name: '不考虑风偏的射击向量：',
    angle: 0,
    distance: 0,
  },
  {
    name: '风偏矫正后射击向量（手动矫正）：',
    angle: 0,
    distance: 0,
  },
])
// 风偏向量（计算结果值）
const windVector: Ref<PolarVector> = ref({
  name: 'windVector',
  angle: 0,
  distance: 0,
})
/**
 * +1 +5 等按钮的回调函数
 * @param change 增加还是减少
 * @param num 要改变的数字
 * @param index 是windVectorMeasurementData中的第几个元素
 * @param angleOrDistance 要改变的是角度还是距离
 */
const handleChangeNumClick = (
  change: 'add' | 'sub',
  num: number,
  index: number,
  angleOrDistance: 'angle' | 'distance',
) => {
  if (angleOrDistance === 'angle') {
    windVectorMeasurementData.value[index].angle =
      change === 'add'
        ? windVectorMeasurementData.value[index].angle + num
        : windVectorMeasurementData.value[index].angle - num
  } else if (angleOrDistance === 'distance') {
    windVectorMeasurementData.value[index].distance =
      change === 'add'
        ? windVectorMeasurementData.value[index].distance + num
        : windVectorMeasurementData.value[index].distance - num
  }
}
/**
 * 从“无风偏射击向量计算器”中，获取不考虑风偏的射击向量，填充进windVectorMeasurementData中
 */
const windVectorMeasurementDataGetNoWindEffectShotVector = () => {
  windVectorMeasurementData.value[0].angle = Number(shotVector.value.angle.toFixed(1))
  windVectorMeasurementData.value[0].distance = Number(shotVector.value.distance.toFixed(1))
}
/**
 * 计算风偏向量按钮回调函数
 */
const handleWindCalculateClick = () => {
  const noWindEffectShotVector = windVectorMeasurementData.value[0]
  const correctedFiringVector = windVectorMeasurementData.value[1]
  windVector.value = windVectorCalculate(noWindEffectShotVector, correctedFiringVector)
  console.log(windVector.value)
}

/**
 * 计算风偏向量（返回极坐标形式）
 * @param noWindEffectShotVector
 * @param correctedFiringVector
 */
const windVectorCalculate = (
  noWindEffectShotVector: PolarVector,
  correctedFiringVector: PolarVector,
): PolarVector => {
  const noWindEffectShotVectorCartesian = polarToCartesian(noWindEffectShotVector)
  const correctedFiringVectorCartesian = polarToCartesian(correctedFiringVector)
  const windX = -(correctedFiringVectorCartesian.x - noWindEffectShotVectorCartesian.x)
  const windY = -(correctedFiringVectorCartesian.y - noWindEffectShotVectorCartesian.y)
  return cartesianToPolar({
    name: '风偏向量',
    x: windX,
    y: windY,
  })
}

// 侦听变化，自动计算风偏
watch(windVectorMeasurementData, handleWindCalculateClick, { deep: true })
// #endregion
// ==================风偏修正工具===========================
// #region
// 风偏修正表格数据源
const windCorrectorData: Ref<PolarVector[]> = ref([
  {
    name: '不考虑风偏的射击向量：',
    angle: 0,
    distance: 0,
  },
  {
    name: '风偏向量：',
    angle: 0,
    distance: 0,
  },
])
// 风偏矫正后射击向量
const correctedShotVector: Ref<PolarVector> = ref({
  name: 'correctedShotVector',
  angle: 0,
  distance: 0,
})

/**
 * 从“无风偏射击向量计算器”中，获取不考虑风偏的射击向量，填充进windCorrectorData中
 */
const windCorrectorDataGetNoWindEffectShotVector = () => {
  windCorrectorData.value[0].angle = Number(shotVector.value.angle.toFixed(1))
  windCorrectorData.value[0].distance = Number(shotVector.value.distance.toFixed(1))
}
/**
 * 从“风偏测量工具”中，获取风偏向量，填充进windCorrectorData中
 */
const windCorrectorDataGetWindVector = () => {
  windCorrectorData.value[1].angle = Number(windVector.value.angle.toFixed(1))
  windCorrectorData.value[1].distance = Number(windVector.value.distance.toFixed(1))
}

/**
 * 处理风偏修正的回调函数
 */
const handleCorrectWindEffectClick = () => {
  correctedShotVector.value = correctWindEffect(
    windCorrectorData.value[1],
    windCorrectorData.value[0],
  )
}

/**
 * 修正风偏函数
 * @param windVector
 * @param noWindEffectShotVector
 */
const correctWindEffect = (windVector: PolarVector, noWindEffectShotVector: PolarVector) => {
  const windVectorCartesian = polarToCartesian(windVector)
  const noWindEffectShotVectorCartesian = polarToCartesian(noWindEffectShotVector)
  return cartesianToPolar({
    name: 'correctedShotVector',
    x: noWindEffectShotVectorCartesian.x - windVectorCartesian.x,
    y: noWindEffectShotVectorCartesian.y - windVectorCartesian.y,
  })
}
// 侦听变化，自动修正风偏
watch(windCorrectorData, handleCorrectWindEffectClick, { deep: true })
// #endregion
/**
 * 极坐标表示法转换为直角坐标表示法
 * @param vector
 */
const polarToCartesian = (vector: PolarVector): CartesianVector => {
  const x = vector.distance * Math.cos((vector.angle * Math.PI) / 180)
  const y = vector.distance * Math.sin((vector.angle * Math.PI) / 180)
  return {
    name: vector.name,
    x,
    y,
  }
}
/**
 * 直角坐标表示法转换为极坐标表示法
 * @param vector
 */
const cartesianToPolar = (vector: CartesianVector): PolarVector => {
  const angle = (Math.atan2(vector.y, vector.x) * 180) / Math.PI
  const distance = Math.sqrt(vector.x * vector.x + vector.y * vector.y)

  return {
    name: vector.name,
    angle: angle < 0 ? angle + 360 : angle,
    distance: distance,
  }
}

/**
 * 将向量翻转180度
 * @param vector
 */
const invertVector = (vector: PolarVector): PolarVector => {
  return {
    name: vector.name,
    angle: (180 + 360 + vector.angle) % 360,
    distance: vector.distance,
  }
}
</script>

<style scoped>
.childMiddle {
  display: flex;
  align-items: center;
}
.divider {
  border-top: 1px #dcdfe6 solid;
  display: block;
  height: 1px;
  margin: 5px 0;
  width: 100%;
}
.front-color-gray {
  color: #404040;
}
.fromular {
  color: #404040;
  font-size: 14px;
  margin-top: 15px;
}
</style>
